/* Includes ------------------------------------------------------------------*/
#include <main.h>

/* Private define-------------------------------------------------------------*/
#define KEY2_State P33

#define Set_Press_TIME          TIMER_2S            //设置长按时间
#define Set_Double_Click_TIME   TIMER_200MS         //设置双击时间

/* Private variables----------------------------------------------------------*/
static uint8_t Click_Buf = FALSE;                 //单击状态缓存
static void KEY_Detect();

/* Public variables-----------------------------------------------------------*/
KEY_t KEY2 = {FALSE,FALSE,FALSE,FALSE,KEY_Detect};	//标志位初始化
STA_Machine_t  STA_Machine = {STA1_KEY_Up,0,0,0};		//状态和定时器初始化

/* Private function prototypes------------------------------------------------*/

/*
* @name   KEY_Detect
* @brief  按键2检测(状态机)
* @param  None
* @retval None   
*/
static void KEY_Detect()
{
    //状态机扫描定时器计时大于或等于10ms，进入一次状态机
    if(STA_Machine.ucSTA_Machine_Scan_Timer >= TIMER_10MS)
    {
      //喂狗
      WatchDog.Feed();
      
      switch (STA_Machine.ucSTA_Machine_Status)
      {
        //按键弹起
        case STA1_KEY_Up:
        {
          if(KEY2_State == 0)                                          
          {
            //切换到状态2
            STA_Machine.ucSTA_Machine_Status = STA2_KEY_DownShake;  
          }
          else
          {
            //按键没被按下，则判断是否有单击缓存
            if(Click_Buf == TRUE)
            {
              //如果双击定时器大于200ms后，说明没在规定时间内进行双击，判断上一次按下是单击操作
              /*如果双击定时器小于200ms，则下面判断不成立，说明还有时间完成双击操作，再按下按键后
              就从状体1到状态2再到状态3，状态3里判断是双击操作*/
              if(STA_Machine.usKEY2_Double_Click_Timer >= Set_Double_Click_TIME)
              {
                KEY2.KEY_Flag = TRUE;
                KEY2.Click    = TRUE;

                //清除单击缓存
                Click_Buf = FALSE;
              }
            }
          }
          break;
        }
        //按下抖动
        case STA2_KEY_DownShake:
        {
          if(KEY2_State == 0)
          {
            //切换到状态3
            STA_Machine.ucSTA_Machine_Status = STA3_KEY_Down;
            //长按定时器清0，开始计算长按时间
            STA_Machine.usKEY2_Press_Timer = 0;
          }
          else
          {
            //如果检测到高电平说明是抖动，切回到状态1
            STA_Machine.ucSTA_Machine_Status = STA1_KEY_Up;             
          }
          break;
        }
        //按键按下
        case STA3_KEY_Down:
        {
          if(KEY2_State == 1)
          {
            //切换到状态4
            STA_Machine.ucSTA_Machine_Status = STA4_KEY_UpShake;
            //不是长按操作，则判断是不是双击操作
            if(KEY2.Press == FALSE)
            {
              //双击检测
              //有单击缓存，说明前面已经单击一次，这次就判断为双击操作
              if(Click_Buf == TRUE)
              {
                KEY2.KEY_Flag     = TRUE;
                KEY2.Double_Click = TRUE;
                //清除单击缓存，为下一次双击准备
                Click_Buf = FALSE;
              }
              else
              {
                //没有单击缓存，说明这是双击的第一次点击，则进行缓存
                Click_Buf = TRUE;
                /*双击定时器清零，开始计算双击时间，如果在双击时间内，再次进入到状态3，则判断是双击操作，
                如果在状态1里超时了，则状态1里检测为单击*/
                STA_Machine.usKEY2_Double_Click_Timer = 0;
              }
            }   
          }
          else
          {
            //长按检测
            if(KEY2.Press == FALSE)
            {
              /*如果长按定时器超过两秒，认为是长按，进入判断体内将长按标志位置TRUE；如果在两秒内松开了按键
              则会判断是不是双击，去执行判断双击的情况*/
              if(STA_Machine.usKEY2_Press_Timer >= Set_Press_TIME)
              {
								STA_Machine.ucSTA_Machine_Status = STA4_KEY_UpShake;
                /*为什么要切换到状态4？
                
                解释：因为这里将KEY2.Press置TRUE后，后面执行一次按键动作，指示灯闪一下，随后KEY2.Press被清零；
                      下一个10ms再进入函数时，状态位还是3，还是进入这里执行，KEY2.Press又会被置成TRUE，所以一直
                      按住不放的话，指示灯就会一直闪，而不是闪一下的情况

                      而在这里第一次进来后将状态位切换到4，KEY2.Press还是会置TRUE，后面指示灯闪一下，KEY2.Press
                      被清零，下一个10ms进来后会直接跳到状态4，所以KEY2.Press不会再次被置TRUE，后面指示灯动作不会
                      再执行，所以只闪一下*/
                KEY2.KEY_Flag = TRUE;
                KEY2.Press    = TRUE;
                
                //因为已经判断为长按，所以不是双击操作，把单击缓存清0
                if(Click_Buf == TRUE)
                {
                  Click_Buf = FALSE;
                }
              }
            }
          }
          break;
        }
        //弹起抖动
        case STA4_KEY_UpShake:
        {
          if(KEY2_State == 1)
          {
            //切换到状态1，完成一次按键动作
            STA_Machine.ucSTA_Machine_Status = STA1_KEY_Up;
          }
          /*如果KEY2_State == 0，不跳回状态3，避免反复检测长按的情况*/
          break;
        }
        default:
            //默认情况都切换到状态1
            STA_Machine.ucSTA_Machine_Status = STA1_KEY_Up;             
          break;
      }

      // /****执行按键动作，用于检测按键效果****/
      // //单击动作 -> 指示灯翻转
      // if(KEY2.KEY_Flag == TRUE)
      // {
      //   if(KEY2.Click == TRUE)
      //   {
      //     Run_LED.Run_LED_Flip();
      //   }

      //   //长按动作 -> 指示灯闪一下
      //   if(KEY2.Press == TRUE)
      //   {
      //     Run_LED.Run_LED_Flip();
      //     Public.Delay_ms(100);
      //     Run_LED.Run_LED_Flip();
      //   }

      //   //双击动作 -> 指示灯闪三下
      //   if(KEY2.Double_Click == TRUE)
      //   {
      //     Run_LED.Run_LED_Flip();
      //     Public.Delay_ms(100);
      //     Run_LED.Run_LED_Flip();
      //     Public.Delay_ms(100);
      //     Run_LED.Run_LED_Flip();
      //     Public.Delay_ms(100);
      //     Run_LED.Run_LED_Flip();
      //     Public.Delay_ms(100);
      //     Run_LED.Run_LED_Flip();
      //     Public.Delay_ms(100);
      //     Run_LED.Run_LED_Flip();
      //   }
      // }

      //按键状体位清零，为下一次按下准备
      // KEY2.Click        = FALSE;
      // KEY2.Press        = FALSE;
      // KEY2.Double_Click = FALSE;

      //状态机扫描定时器清零，开始下一次扫描
      STA_Machine.ucSTA_Machine_Scan_Timer = 0;
    }
}

/********************************************************
  End Of File
********************************************************/